package trie;

import java.util.TreeMap;

/**
 * @program: play-structure
 * @author: baichen
 * 677. 键值映射
 * 实现一个 MapSum 类里的两个方法，insert 和 sum。
 * 对于方法 insert，你将得到一对（字符串，整数）的键值对。字符串表示键，整数表示值。
 * 如果键已经存在，那么原来的键值对将被替代成新的键值对。
 * 对于方法 sum，你将得到一个表示前缀的字符串，你需要返回所有以该前缀开头的键的值的总和。
 * 示例：
 * 输入: insert("apple", 3), 输出: Null
 * 输入: sum("ap"), 输出: 3
 * 输入: insert("app", 2), 输出: Null
 * 输入: sum("ap"), 输出: 5
 **/
public class MapSum {
    private class Node {
        public int value;       //键值对对应的value,当key为Word是value有值，否则为0
        // 到下一个节点的映射，字符串是Character,可以根据实际情况替换为别的数据类型
        // 从Character到Node，从字符映射到节点
        public TreeMap<Character, Node> next;

        public Node(int value) {
            this.value = value;
            next = new TreeMap<>();
        }

        public Node() {
            this(0);    //默认不是单词，则value为0
        }
    }

    private Node root;

    /**
     * Initialize your data structure here.
     */
    public MapSum() {
        root = new Node();
    }

    //新增单词及其对应的value
    public void insert(String word, int val) {
        Node cur = root;
        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            //这里是使用了映射，字符映射到节点，所以根据字符查找这个节点是否存在
            //如果为空(即不存在)则存入这个字符并新建一个节点
            if (cur.next.get(c) == null) {
                cur.next.put(c, new Node());
            }
            //如果存在则直接指向这个节点，新增这个字符对应的节点
            cur = cur.next.get(c);
        }
        cur.value = val;        //添加完单词后，要给这个单词对应的value赋值
    }

    public int sum(String prefix) {
        Node cur = root;
        for (int i = 0; i < prefix.length(); i++) { //遍历prefix
            char c = prefix.charAt(i);
            if (cur.next.get(c) == null) {
                return 0;
            }
            cur = cur.next.get(c);
        }
        return sum(cur);
    }

    //遍历以node为根的树，将其所有节点对应的value求和
    private int sum(Node node) {
        //递归终止的条件node为叶子结点,不过不加这个也是可以的
//        if (node.next.size()==0){
//            return node.value;
//        }
        int result = node.value;    //当前node对应的值
        for (char c : node.next.keySet()) {    //node可以指向的所有的字符的下一个节点
            result += sum(node.next.get(c));
        }
        return result;
    }
}

/**
 * Your MapSum object will be instantiated and called as such:
 * MapSum obj = new MapSum();
 * obj.insert(key,val);
 * int param_2 = obj.sum(prefix);
 */
